package com.kt.common.coroutines

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

/*
fun main() = runBlocking<Unit> {
    //1
    //4
    //9
    //16
    //25
    //done
    val channel = Channel<Int>()
    launch {
        // 这里可能是消耗大量 CPU 运算的异步逻辑，我们将仅仅做 5 次整数的平方并发送
        for (x in 1..5) channel.send(x * x)
    }
    repeat(5){
        println(channel.receive())
    }
    println("done")
}*/


/*fun main() = runBlocking<Unit> {
    val channel = Channel<Int>()
    launch {
        for (x in 1..5) channel.send(x * x)
        channel.close() // 我们结束发送
    }
// 这里我们使用 `for` 循环来打印所有被接收到的元素（直到通道被关闭）
    for (y in channel) println(y)
    println("Done!")
}*/

/*
fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (y in 1..5) send(y * 2)
}

fun main() = runBlocking<Unit> {
    val squares = produceSquares()
    squares.consumeEach {
        println(it)
    }
    println("done")
}*/

//管道
/*fun CoroutineScope.produceNumbers(): ReceiveChannel<Int> = produce {
    var x = 3
    while (true) send(x++)
}

fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
    for (x in numbers) send(x * x)
}*/

/*
fun main() = runBlocking{
    val numbers = produceNumbers() // 从 1 开始生成整数
    val squares = square(numbers) // 整数求平方
    repeat(3) {
        println(squares.receive()) // 输出前五个
    }
    println("Done!") // 至此已完成
    coroutineContext.cancelChildren() // 取消子协程
}
*/

fun CoroutineScope.produceNumbers() = produce<Int> {
    var x = 1 // 从 1 开始
    while (true) {
        send(x++) // 产生下一个数字
        delay(100) // 等待 0.1 秒
    }
}

fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
    for (msg in channel) {
        println("Processor #$id received $msg")
    }
}

//fun main() = runBlocking<Unit> {
//    val producer = produceNumbers()
//    repeat(5) { launchProcessor(it, producer) }
//    delay(950)
//    producer.cancel() // 取消协程生产者从而将它们全部杀死
//}

/*fun main() = runBlocking {
    val channel = Channel<String>()
    launch { sendString(channel, "foo", 200L) }
    launch { sendString(channel, "BAR!", 500L) }
    repeat(6) { // 接收前六个
        println(channel.receive())
    }
    coroutineContext.cancelChildren() // 取消所有子协程来让主协程结束
}

suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
    while (true) {
        delay(time)
        channel.send(s)
    }
}*/



fun main() = runBlocking<Unit> {
    val channel = Channel<Int>(3) // 启动带缓冲的通道
    val sender = launch { // 启动发送者协程
        repeat(10) {
            println("Sending $it") // 在每一个元素发送前打印它们
            channel.send(it) // 将在缓冲区被占满时挂起
        }
    }
    // 没有接收到东西……只是等待……
    delay(1000)
    sender.cancel() // 取消发送者协程
}